package wsi.task.map;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.rygh.core.html.Html;
import org.rygh.core.html.table.HtmlTable;
import org.rygh.core.html.table.TableData;
import org.rygh.core.html.table.TableTuple;
import org.rygh.core.model.common.MapList;
import org.rygh.core.model.common.StringSet;
import org.rygh.core.util.counter.SimpleCounter;
import org.rygh.core.xml.XmlPath;

import wsi.dataguide.tree.WSXmlLeaf;
import wsi.subgraph.tree.EntityBranch;

public class MappingStatistics {

	private final SimpleCounter<StatisticsKey> counter = new SimpleCounter<>();
	private MapCandidate mapCandidate;
	private int callCount = 0;

	public MappingStatistics() {

	}

	public HtmlTable getHtmlTable() {
		HtmlTable table;
		TableData data;

		TableTuple tuple;

		data = new TableData();
		tuple = new TableTuple();
		tuple.add("Source");
		tuple.add("Predicates");
		tuple.add("Frequency");
		tuple.add("Destination");
		data.add(tuple);

		for (StatisticsKey key : counter.keySet()) {
			tuple = new TableTuple();
			tuple.add(key.getSourceXPath().getValue());
			tuple.add(key.getPredicates().toString());
			tuple.add(String.format("%.3f", (float) counter.get(key)
					/ callCount));
			tuple.add(key.getDestXPath().getValue());
			data.add(tuple);
		}

		data.sort();

		table = new HtmlTable("Statistics", data, false);
		return table;
	}

	public void setMapCandidate(MapCandidate mapCandidate) {
		this.mapCandidate = mapCandidate;
		callCount++;
	}

	@Override
	public String toString() {
		Html html = new Html("Statistics");

		html.addElement(getHtmlTable());

		return html.toString();
	}

	public void update() {
		XmlPath spath, dpath;
		StringSet predicates;
		StatisticsKey key;
		List<EntityBranch> branches;

		Map<WSXmlLeaf, XmlPath> xpathmap = mapCandidate.getXPathMap();
		MapList<String, WSXmlLeaf> gmap = mapCandidate.getLeafGroupMap();
		MapCandidateCache cachemap = mapCandidate.getCache();

		StringBuilder sb = new StringBuilder();

		for (WSXmlLeaf s : mapCandidate.getSources()) {
			sb.append(s.getXpath().getValue());
			sb.append("<br>");
		}

		XmlPath spath2 = new XmlPath(sb.toString());

		for (WSXmlLeaf s : mapCandidate.getSources()) {
			spath = s.getXpath();

			System.out.println("stat spath " + spath);

			for (Entry<String, List<WSXmlLeaf>> j : gmap.entrySet()) {

				for (WSXmlLeaf l : j.getValue()) {
					dpath = xpathmap.get(l);
					branches = cachemap.get(cachemap.getStringSetKey(s, l));

					for (EntityBranch b : branches) {
						predicates = b.getPredicateKey();

						key = new StatisticsKey(spath2, dpath, predicates);

						counter.count(key);
					}
				}

			}

			/*
			 * For a MapCandidate, if it contains multiple sources, then the
			 * sources have the same StringSet. We only need to process for the
			 * first one.
			 */
			break;
		}

	}
}
